<html>
 <head>
  <link rel="stylesheet" type="text/css" href="../../core/foam.css" />
  <link rel="stylesheet" type="text/css" href="mreader.css" />
  <script>var FOAM_BOOT_DIR="../../core/";</script>
  <script language="javascript" src="../../core/bootFOAM.js"></script>
  <title>Mail Reader</title>
 </head>
<body style="overflow:hidden;margin-top:5px;">
<table>
  <tr>
  <td>
  </td>
  <td>
    <div class="title"></div>
    <div class="subtitle"> &nbsp;MBOX Reader</div>
  </td>
  <td width=90%></td>
  <td valign="top">
  <div class="titleBar">
<span style="float:right; margin-top: 23px;color:#666">MBOX File:<input type="file" onchange="loadmbox(event);"></span>
  </div>
  </td>
  </tr>
</table>
<hr color="#9BC0FA">
<div id="search" style="position:absolute;background-color:#fff;">
  <div id="subjectSearch"  class="searchTitle"></div>
  <div id="toSearch"       class="searchTitle"></div>
  <div id="fromSearch"     class="searchTitle"></div>
  <div id="labelSearch"    class="searchTitle"></div>
  <div onClick="resetSearch()" style="float:right" class="searchTitle"><u>Clear All</u></div>
  <div id="viewMode"       class="searchTitle"></div>
</div>
<div id="browse" style="position:absolute;background-color:#FFF;float:left;"></div>
<div id="edit" style="position:absolute;margin-top:10px;margin-right:15px;border-width:1px;border-style:solid;border-color:black;position:absolute;background-color:#FFF;">
</div>
<div id="footer" style="position:absolute;text-align:left;padding-top:3px;">
 <!-- <hr color="#9BC0FA"> -->
  <font size=-1 face="catull" style="padding-left:10px;text-shadow:rgba(64,64,64,0.3) 3px 3px 4px;">
  <font color="#3333FF">F</font><font color="#FF0000">O</font><font color="#ddaa00">A</font><font color="#33CC00">M</font>
  <font color2="#555555"> POWERED</font>
  <div onClick="switchHands()" style="float:right;padding-right:10px;" class="searchTitle"><u>switch hands</u></div>
</div>
<script>
var GROUP_PROPERTY = EMail.CONV_ID;
var expanded = {};

var ThreadedEMail = EMail.deepClone();
ThreadedEMail.properties.push(Property.create({
  name: 'count',
  tableWidth: 45,
  label: 'Count',
  type: 'int',
  tableFormatter: function(c, email, table) {
    if ( c ) {
      if ( c == 1 ) return "&nbsp;&nbsp;&nbsp;&nbsp;1";
      var isExpanded = expanded[GROUP_PROPERTY.f(email)];
      var icon = isExpanded ? "&nbsp;-" : "+";
      var id = table.on('click', (function(isExpanded) { return function() {
        if ( isExpanded ) {
          delete expanded[GROUP_PROPERTY.f(email)];
        } else {
          expanded[GROUP_PROPERTY.f(email)] = true;
        }
        updateQuery();
      }})(isExpanded));
      return '<span id=' + id + '>' + icon + '</span>' + "&nbsp;&nbsp;" + c;
    }
    return "";
  },
}));
ThreadedEMail.tableProperties.unshift('count');

EMail.ATTACHMENTS.compare = function(o1, o2) {
  return this.f(o1).length - this.f(o2).length;
};


// var header = $('header');
var footer = $('footer');
var search = $('search');
var browse = $('browse');
var edit   = $('edit');

var reversed = false;

function pos(e, top, left, width, height) {
  var s = e.style;
  left = left || 0;

  if ( reversed ) left = (window.innerWidth - 15) - left - (width || toNum(e.style.width));

  top != null && (e.style.top = toNum(top) + 'px');
  left != null && (e.style.left = toNum(left) + 'px');
  width != null && (e.style.width = toNum(width) + 'px');
  height != null && (e.style.height = toNum(height) + 'px');
}

var MIN_THREE_COLUMN_W = 1600;
var table;

function layout() {
  var W         = window.innerWidth - 15;
  var H         = window.innerHeight-5;
  var HEADER_H  = 85;
  var FOOTER_H  = 20;
  var SEARCH_W  = 400;
  var SEARCH_H  = H - HEADER_H - FOOTER_H;
  var RIGHT_W   = W - SEARCH_W - 5;

//  pos(header,null,null,W,HEADER_H-10);
  pos(search, HEADER_H, null, SEARCH_W, SEARCH_H);

  if ( W > MIN_THREE_COLUMN_W ) {
    pos(browse, HEADER_H, SEARCH_W + 10, RIGHT_W * 0.6, SEARCH_H+70); // ??? Why is the 70 needed
    pos(edit, HEADER_H, SEARCH_W + 10 + RIGHT_W * 0.6, RIGHT_W * 0.4-10, SEARCH_H-15);
  } else {
    pos(browse, HEADER_H, SEARCH_W + 10, RIGHT_W, SEARCH_H/2);
    pos(edit,
      toNum(browse.style.top) + toNum(browse.style.height) + 5,
      SEARCH_W + 10,
      RIGHT_W-10,
      SEARCH_H / 2 -20);
  }
   pos(footer, H-FOOTER_H, null, W, FOOTER_H);

  table && table.layout();
}

window.onresize = layout;
layout();

    emails = IDBDAO.create({model: EMail});

    var dao = MDAO.create({model: EMail});
    dao.addIndex(EMail.TIMESTAMP);
    // dao.addIndex(EMail.CONV_ID);
    dao.addIndex(EMail.TO);
    dao.addIndex(EMail.FROM);
    dao.addIndex(EMail.SUBJECT);

//    var dao = [];

/*    dao = PartitionDAO.create({ partitions: [
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail }),
        WorkerDAO.create({ model: EMail })
 ] });
*/
/*
    dao.index = AltIndex.create(
      TreeIndex.create(EMail.TIMESTAMP,    ValueIndex),
      TreeIndex.create(EMail.TO,      AltIndex.create(
        TreeIndex.create(EMail.FROM, TreeIndex.create(EMail.TIMESTAMP, ValueIndex)),
        TreeIndex.create(EMail.TIMESTAMP, ValueIndex)
      )),
      TreeIndex.create(EMail.FROM,    TreeIndex.create(EMail.TIMESTAMP, ValueIndex)),
      TreeIndex.create(EMail.SUBJECT, TreeIndex.create(EMail.TIMESTAMP, ValueIndex))
    );
*/
//    dao2.bulkLoad(dao2);

    var d1 = dao;
    var d2 = emails;

    var lock = {};

    var idbPerf;

    dao = {
      __proto__: dao,
      find: function(query, sink) {
        console.log('find:', query);
        d1.find(query, sink);
      },

      select2: function(sink, options) {
        var future = afuture();

        var s = CountExpr.isInstance(sink) ? COUNT() : { put: function() { } };

         asynchronized(aseq(
//          alog('select ', sink, options && options.query && options.query.toSQL() || 'TRUE', options && options.skip, options && options.limit),
//          atime('indexedDB', arepeat(1, function(ret) { d2.select(s, options)(ret); }), function(p) { idbPerf = p; }),
//          alog('indexedDB to MDAO'),
//          atime('idao', arepeat(100, function(ret) { d1.select(s, options)(ret); }), function(p) { console.log(idbPerf + ',' + (p/1000)); }),
          function(ret) { d1.select(sink, options)(function(v) { future.set(sink); ret(); }); }
        ),lock)(anop);

        return future.get;
      }
    };


    // Quick hack to make search work on each keystroke
    // TODO: make option of TextSearchView
    DomValue.DEFAULT_EVENT = 'keyup';

    table = ScrollBorder.create({
      view: TableView.create({
        model: EMail,
        dao: dao,
        rows: 20
      }),
      dao: dao
    });

    var searchSubject = TextSearchView.create({width:57, label: 'Search', property: CONCAT(EMail.SUBJECT, EMail.BODY)});
    var byTo     = GroupBySearchView.create({size: 9, dao: dao, property: EMail.TO});
    var byFrom   = GroupBySearchView.create({size: 11, dao: dao, property: EMail.FROM});
    var byLabel  = GroupBySearchView.create({size: 6, dao: dao, property: EMail.LABELS});
    var viewMode = RadioBoxView.create({value:SimpleValue.create('Message'), choices: ['Message', 'Conversation']});

    browse.innerHTML = table.toHTML();
    searchSubject.insertInElement('subjectSearch');
    viewMode.insertInElement('viewMode');
    byTo.insertInElement('toSearch');
    byFrom.insertInElement('fromSearch');
    byLabel.insertInElement('labelSearch');

    table.initHTML();

    table.view.selection.addListener(function (src, property, oldValue, newValue) {
       if ( ! newValue ) return;
       var editView = SummaryView.create({value: table.view.selection});
       editView.model = EMail;
       edit.innerHTML = editView.toHTML();
       editView.initHTML();
    });

    table.view.selection.set(table.view.objs[0]);

    layout();

    function updateQuery() {
      var predicate = AND(
        searchSubject.predicate,
        byFrom.predicate,
        byTo.predicate,
        byLabel.predicate).partialEval();

      // console.log('query: ', predicate.toSQL());

      table.scrollbar.value = 0;

      if ( viewMode.value.get() === 'Message' ) {
        table.view.model = EMail;
        table.dao = dao.where(predicate);
      } else {
        table.view.model = ThreadedEMail;
        dao.where(predicate).select(ExpandableGroupByExpr.create({
          arg1: GROUP_PROPERTY,
          arg2: EMail.TIMESTAMP,
          expanded: expanded
        }))(function(groups) {
          table.dao = groups;// .values;
        });
      }

      byFrom.filter  = AND(searchSubject.predicate, byTo.predicate,   byLabel.predicate).partialEval();
      byTo.filter    = AND(searchSubject.predicate, byFrom.predicate, byLabel.predicate).partialEval();
      byLabel.filter = AND(searchSubject.predicate, byTo.predicate,   byFrom.predicate).partialEval();
    }

    viewMode.value.addListener(updateQuery);

    Events.dynamic(function() {
      searchSubject.predicate;
      byFrom.predicate;
      byTo.predicate;
      byLabel.predicate;
    },
    updateQuery);

    function resetSearch() {
      byFrom.view.value.set(''); byTo.view.value.set(''); byLabel.view.value.set('');
      byFrom.filter = byTo.filter = byLabel.filter = TRUE;
      table.dao = dao;
    }

    function switchHands() { reversed = ! reversed; layout(); }

    function loadmbox(event) {
      emails.removeAll(); // this only works with storagedao because its synchronous
      var file = event.target.files[0];

      MBOXLoader.dao = emails;
      SourceBlob(file, BlobToText(TextToLines(MBOXLoader)));
    }

    var a = [];
    emails.select(a)(function() {
      console.log('********************************************** loaded');
      // Copy values from the array into the dao in an order
      // which will cause a balanced tree to be created.
      function bcopy(s,e) {
        if ( s == e ) dao.put(a[s]);
        if ( e <= s ) return;
        var m = Math.floor((s+e)/2);
        dao.put(a[m]);
        bcopy(s,m-1);
        bcopy(m+1,e);
      }
      bcopy(0, a.length-1);
      a = undefined;

      console.log('********************************************** inserted');
      layout();
      byTo.dao = byTo.dao;
      byFrom.dao = byFrom.dao;
      byLabel.dao = byLabel.dao;
      resetSearch();
    });

   TemplateUtil = undefined;
  </script>
</body>
</html>
